package com.xnyzc.lhy.order.service.impl.order;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.xnyzc.lhy.common.component.redis.RedisCommon;
import com.xnyzc.lhy.common.constant.MessageConstant;
import com.xnyzc.lhy.common.constant.MqConstant;
import com.xnyzc.lhy.common.constant.RedisPrefixConstant;
import com.xnyzc.lhy.common.entity.Qd;
import com.xnyzc.lhy.common.entity.Rv;
import com.xnyzc.lhy.common.exception.PangException;
import com.xnyzc.lhy.common.penum.EErrorCode;
import com.xnyzc.lhy.common.penum.order.EBillType;
import com.xnyzc.lhy.common.penum.order.ECancelOrderType;
import com.xnyzc.lhy.common.penum.order.EDiDiOrderStatus;
import com.xnyzc.lhy.common.penum.order.EOrderStatus;
import com.xnyzc.lhy.common.util.*;
import com.xnyzc.lhy.order.entity.common.order.OrderCommon;
import com.xnyzc.lhy.order.entity.gps.OaDVehicleGps;
import com.xnyzc.lhy.order.entity.order.DriverCancelOrderRecord;
import com.xnyzc.lhy.order.entity.order.OaCOrderPersonal;
import com.xnyzc.lhy.order.entity.order.OaDOrder;
import com.xnyzc.lhy.order.entity.param.order.*;
import com.xnyzc.lhy.order.entity.param.synchronization.StatusCallbackParam;
import com.xnyzc.lhy.order.entity.system.OaSysGlobalConfig;
import com.xnyzc.lhy.order.entity.user.OaDUser;
import com.xnyzc.lhy.order.entity.user.message.OaSysMessage;
import com.xnyzc.lhy.order.feign.message.FeignMessageService;
import com.xnyzc.lhy.order.mapper.order.*;
import com.xnyzc.lhy.order.mapper.system.OaSysGlobalConfigMapper;
import com.xnyzc.lhy.order.mapper.user.OaDUserMapper;
import com.xnyzc.lhy.order.mo.OrderLogMo;
import com.xnyzc.lhy.order.mq.MqOrderProducer;
import com.xnyzc.lhy.order.service.order.OaDOrderOperationService;
import com.xnyzc.lhy.order.service.user.message.IOaSysMessageService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.util.*;

/**
 * <p>
 * 司机订单操作相关 服务类
 * </p>
 *
 * @author lhy@xnyzc.com
 * @since 2019-10-31
 */
@Service
@Slf4j
public class OaDOrderOperationServiceImpl implements OaDOrderOperationService {

    @Autowired
    private OaDUserMapper oaDUserMapper;

    @Autowired
    private OrderCommon orderCommon;

    @Autowired
    private RedisCommon redisCommon;

    @Autowired
    private OaSysGlobalConfigMapper oaSysGlobalConfigMapper;

    @Autowired
    private OaCOrderPersonalMapper oaCOrderPersonalMapper;

    @Autowired
    private DriverCancelOrderRecordMapper driverCancelOrderRecordMapper;

    @Autowired
    private OaDOrderMapper oaDOrderMapper;

    @Autowired
    private MqOrderProducer producer;

    @Autowired
    private IOaSysMessageService iOaSysMessageService;

    @Autowired
    private MongoTemplate mongoTemplate;


    /**
     * 司机端取消订单
     *
     * @return
     */
    @Override
    public Rv dOrderCancel(OrderInfoParam orderInfoParam) {
        Long driverId = TokenUtil.getTokenUserId();
        if (CheckUtil.objIsEmpty(driverId, orderInfoParam.getOrderNo())) {
            throw PangException.create(EErrorCode.missingArg);
        }
        OaDUser user = oaDUserMapper.selectById(driverId);
        List<OaSysGlobalConfig> oaSysGlobalConfigsList = oaSysGlobalConfigMapper.selectList(null);
        OaCOrderPersonal oaCOrderPersonal = oaCOrderPersonalMapper.selectOne(Wrappers.<OaCOrderPersonal>lambdaQuery().eq(OaCOrderPersonal::getDriverId, driverId).eq(OaCOrderPersonal::getOrderNo, orderInfoParam.getOrderNo()));
        if (CheckUtil.objIsEmpty(user, oaSysGlobalConfigsList, oaCOrderPersonal)) {
            throw PangException.create(EErrorCode.noData);
        }
        OaSysGlobalConfig oaSysGlobalConfig = oaSysGlobalConfigsList.get(0);
        Integer cancelNumber = oaSysGlobalConfig.getCancelNumber();

        boolean temporaryCancel = false;
        Integer waitingTime = oaSysGlobalConfig.getWaitingTime();
        Calendar newTime = Calendar.getInstance();
        newTime.add(Calendar.MINUTE, -waitingTime);
        if (oaCOrderPersonal.getOrderStatus().equals(EOrderStatus.reservationLocation.getType()) || oaCOrderPersonal.getOrderStatus().equals(EOrderStatus.driverArrived.getType())) {
            if (CheckUtil.objIsNotEmpty(oaCOrderPersonal.getArriveMeetPassengerTime())) {
                if (oaCOrderPersonal.getArriveMeetPassengerTime().getTime() >= newTime.getTime().getTime()) {
                    temporaryCancel = true;
                }
            } else {
                temporaryCancel = true;
            }
        }
        if (temporaryCancel && cancelNumber == 0) {
            throw PangException.create(EErrorCode.cancelOrderNum);
        }
        Date date = new Date();
        // 查询次数
        int recordCount = recordNumber(driverId);
        if (cancelNumber == 0) {
            if (recordCount > cancelNumber) {
                throw PangException.create(EErrorCode.cancelOrderNumber);
            }
        } else {
            if (recordCount >= cancelNumber) {
                throw PangException.create(EErrorCode.cancelOrderNumber);
            }
        }
        // 等待超过多少分钟可以无责取消行程
        recordCancelNumber(driverId, oaSysGlobalConfig, oaCOrderPersonal);
        //向司机端发送取消订单信息
        if (CheckUtil.objIsNotEmpty(driverId)) {
            if (!orderCommon.setDriverIsOrderAndAcceptancOrderStatus(false, true, driverId, "")) {
                log.info("更新司机接单状态失败!");
                throw PangException.create(EErrorCode.cancelAssignVehicleFailure);
            }
        }
        oaCOrderPersonal.setUpdateTime(date);
        oaCOrderPersonal.setUpdateUser(driverId + "");
        oaCOrderPersonal.setTotalFee(new BigDecimal(0));
        oaCOrderPersonal.setOrderStatus(EOrderStatus.driverCancelOrder.getType());
        oaCOrderPersonal.setIsComment(1);
        oaCOrderPersonal.setCancelOrderTime(date);
        oaCOrderPersonal.setCancelReason(ECancelOrderType.replyDriverAfter.getType());
        oaCOrderPersonalMapper.updateById(oaCOrderPersonal);
        OaDOrder oaDOrder = getDOrder(oaCOrderPersonal.getPersonalId());
        //设置司机订单表
        if (CheckUtil.objIsNotEmpty(oaDOrder)) {
            oaDOrder.setOrderStatus(EOrderStatus.driverCancelOrder.getType());
            oaDOrder.setUpdateTime(date);
            oaDOrder.setUpdateUser(driverId);
            oaDOrder.setTotalCost(new BigDecimal(0));
            oaDOrderMapper.updateById(oaDOrder);
        }
        //解除司机锁定
        orderCommon.setDriverIsOrderAndAcceptancOrderStatus(false, true, driverId, "");

        //===========================向滴滴推送司机取消订单信息---start==================================
        StatusCallbackParam statusCallbackParam = new StatusCallbackParam();
        statusCallbackParam.setChannel(oaCOrderPersonal.getOrderChannel());
        statusCallbackParam.setOpen_oid(oaCOrderPersonal.getDidiOrderId());
        statusCallbackParam.setOrder_id(oaCOrderPersonal.getOrderNo());
        statusCallbackParam.setDriver_id(oaCOrderPersonal.getDriverId().toString());
        statusCallbackParam.setStatus(EDiDiOrderStatus.reassigned.getDidiType());
        String str = redisCommon.getStr(RedisPrefixConstant.GPS_VEH_KEY_PREFIX + driverId);
        if (CheckUtil.strIsNotEmpty(str)) {
            OaDVehicleGps oaDVehicleGps = JSON.parseObject(str, OaDVehicleGps.class);
            statusCallbackParam.setDriver_lng(new BigDecimal(oaDVehicleGps.getLng()));
            statusCallbackParam.setDriver_lat(new BigDecimal(oaDVehicleGps.getLat()));
        }
        producer.sendMsg(statusCallbackParam, MqConstant.STATUS_CALL_BACK_SYNC);
        //===========================向滴滴推送司机取消订单信息---end=====================================

        //删除rediskey
        String key = RedisPrefixConstant.ORDER_OA_D_ORDER + oaCOrderPersonal.getOrderNo();
        if (redisCommon.hashKey(key)) {
            if (CheckUtil.objIsNotEmpty(oaCOrderPersonal.getDriverId())) {
                redisCommon.remove(RedisPrefixConstant.ORDER_VEH + oaCOrderPersonal.getDriverId());
            }
            redisCommon.remove(key);
        }
        OaSysMessage oaSysMessage = new OaSysMessage();
        oaSysMessage.setMessageType(1);
        oaSysMessage.setPushCode(EBillType.CANCEL_TRIP.getIdenifition());
        oaSysMessage.setMessageContent(MessageConstant.CANCEL_ORDER_TAIL + oaCOrderPersonal.getPassengerPhoneSuffix() + MessageConstant.THE_TRIP);
        oaSysMessage.setDriverId(oaCOrderPersonal.getDriverId());
        oaSysMessage.setTag(oaCOrderPersonal.getTag());
        iOaSysMessageService.saveMessage(oaSysMessage);
        Qd msg = Qd.create().add("msg", MessageConstant.VOICE_DRIVER_CANCEL_ORDER);
        return Rv.wrap(EErrorCode.success, msg);
    }

    /**
     * 查询每日记录次数
     *
     * @param driverId
     * @return
     */
    public int recordNumber(Long driverId) {
        long zero = System.currentTimeMillis() / (1000 * 3600 * 24) * (1000 * 3600 * 24) - TimeZone.getDefault().getRawOffset();
        long twelve = zero + 24 * 60 * 60 * 1000 - 1;
        QueryWrapper<DriverCancelOrderRecord> wrapper = new QueryWrapper<>();
        wrapper.eq(DriverCancelOrderRecord.DRIVER_ID, driverId);
        wrapper.ge(DriverCancelOrderRecord.CREATE_TIME, new Timestamp(zero));
        wrapper.le(DriverCancelOrderRecord.CREATE_TIME, new Timestamp(twelve));
        int recordCount = driverCancelOrderRecordMapper.selectCount(wrapper);
        return recordCount;
    }

    /**
     * 记录取消次数
     *
     * @param driverId
     * @param oaSysGlobalConfig
     * @param oaCOrderPersonal
     */
    public void recordCancelNumber(Long driverId, OaSysGlobalConfig oaSysGlobalConfig, OaCOrderPersonal oaCOrderPersonal) {
        Date date = new Date();
        Integer waitingTime = oaSysGlobalConfig.getWaitingTime();
        Calendar newTime = Calendar.getInstance();
        newTime.add(Calendar.MINUTE, -waitingTime);
        if (oaCOrderPersonal.getOrderStatus().equals(EOrderStatus.reservationLocation.getType())) {
            // 有责
            recordInsert(date, driverId, oaCOrderPersonal);
        }
        if (oaCOrderPersonal.getOrderStatus().equals(EOrderStatus.driverArrived.getType()) &&
                CheckUtil.objIsNotEmpty(oaCOrderPersonal.getArriveMeetPassengerTime())) {
            if (oaCOrderPersonal.getArriveMeetPassengerTime().getTime() >= newTime.getTime().getTime()) {
                // 有责
                recordInsert(date, driverId, oaCOrderPersonal);
            }
        }
    }

    public void recordInsert(Date date, Long driverId, OaCOrderPersonal oaCOrderPersonal) {
        DriverCancelOrderRecord record = new DriverCancelOrderRecord();
        record.setRecordId(IDUtil.nextId());
        record.setCreateTime(date);
        record.setUpdateTime(date);
        record.setCreateUser(driverId);
        record.setUpdateUser(driverId);
        record.setOrderNo(oaCOrderPersonal.getOrderNo());
        record.setPersonalId(oaCOrderPersonal.getPersonalId());
        record.setTag(TokenUtil.getTag());
        record.setDriverId(driverId);
        driverCancelOrderRecordMapper.insert(record);
    }

    public OaDOrder getDOrder(Long orderId) {
        OaDOrder dOrder = new OaDOrder();
        List<OaDOrder> dOrderList = new ArrayList<>();
        QueryWrapper<OaDOrder> wrapper = new QueryWrapper<>();
        wrapper.eq(OaDOrder.USER_ORDER_NO, orderId);
        dOrderList = oaDOrderMapper.selectList(wrapper);
        if (CheckUtil.objIsNotEmpty(dOrderList)) {
            dOrder = dOrderList.get(0);
        }
        return dOrder;
    }

}
